/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.desmond.squarecamera.util;

import ohos.agp.render.Canvas;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.render.Texture;
import ohos.agp.utils.Matrix;
import ohos.agp.utils.Rect;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;

public class ThumbnailUtils {

    private static final int OPTIONS_SCALE_UP = 0x1;
    public static final int OPTIONS_RECYCLE_INPUT = 0x2;

    public static PixelMap extractThumbnail(
            PixelMap source, int width, int height, int options
    ) {
        if (source == null) {
            return null;
        }

        float scale;
        float sourceWidth = source.getImageInfo().size.width;
        float sourceHeight = source.getImageInfo().size.height;

        if (sourceWidth < sourceHeight) {
            scale = width / sourceWidth;
        } else {
            scale = height / sourceHeight;
        }

        Matrix matrix = new Matrix();
        matrix.setScale(scale, scale);
        PixelMap thumbnail = transform(matrix, source, width, height,
                OPTIONS_SCALE_UP | options);

        return thumbnail;
    }

    private static PixelMap transform(Matrix scaler,
                                      PixelMap source,
                                      int targetWidth,
                                      int targetHeight,
                                      int options) {

        boolean scaleUp = (options & OPTIONS_SCALE_UP) != 0;
        boolean recycle = (options & OPTIONS_RECYCLE_INPUT) != 0;

        int sourceWidth = source.getImageInfo().size.width;
        int sourceHeight = source.getImageInfo().size.height;

        int deltaX = sourceWidth - targetWidth;
        int deltaY = sourceHeight - targetHeight;

        if (!scaleUp && (deltaX < 0 || deltaY < 0)) {
            PixelMap b2 = BitmapUtil.createPixelMap(targetWidth, targetHeight, PixelFormat.ARGB_8888);
            Canvas c = new Canvas(new Texture(b2));

            int deltaXHalf = Math.max(0, deltaX / 2);
            int deltaYHalf = Math.max(0, deltaY / 2);
            Rect src = new Rect(
                    deltaXHalf,
                    deltaYHalf,
                    deltaXHalf + Math.min(targetWidth, sourceWidth),
                    deltaYHalf + Math.min(targetHeight, sourceHeight));

            int dstX = (targetWidth  - src.getWidth())  / 2;
            int dstY = (targetHeight - src.getHeight()) / 2;
            Rect dst = new Rect(
                    dstX,
                    dstY,
                    targetWidth - dstX,
                    targetHeight - dstY);
            c.drawPixelMapHolder(new PixelMapHolder(source),
                    dst.left,
                    dst.top,
                    null);
            if (recycle) {
                source.release();
            }
            c.setTexture(null);
            return b2;
        }

        float pixelMapWidthF = source.getImageInfo().size.width;
        float pixelMapHeightF = source.getImageInfo().size.height;

        float bitmapAspect = pixelMapWidthF / pixelMapHeightF;
        float viewAspect = (float) targetWidth / targetHeight;

        if (bitmapAspect > viewAspect) {
            float scale = targetHeight / pixelMapHeightF;
            if (scale < .9F || scale > 1F) {
                scaler.setScale(scale, scale);
            } else {
                scaler = null;
            }
        } else {
            float scale = targetWidth / pixelMapWidthF;
            if (scale < .9F || scale > 1F) {
                scaler.setScale(scale, scale);
            } else {
                scaler = null;
            }
        }

        PixelMap b1;
        if (scaler != null) {
            b1 = BitmapUtil.createPixelMap(source, 0, 0,
                    sourceWidth, sourceHeight, scaler, true);
        } else {
            b1 = source;
        }

        if (recycle && b1 != source) {
            source.release();
        }

        int dx1 = Math.max(0, b1.getImageInfo().size.width - targetWidth);
        int dy1 = Math.max(0, b1.getImageInfo().size.height - targetHeight);

        PixelMap b2 = BitmapUtil.createPixelMap(b1,
                dx1 / 2,
                dy1 / 2,
                targetWidth,
                targetHeight,
                scaler,
                false);

        if (b2 != b1) {
            if (recycle || b1 != source) {
                b1.release();
            }
        }

        return b2;
    }
}
